package com.stars.easyms.rest.handler;

import com.stars.easyms.base.alarm.EasyMsAlarmAssistor;
import com.stars.easyms.base.util.ReflectUtil;
import com.stars.easyms.feign.exception.BusinessFeignException;
import com.stars.easyms.rest.bean.RestInfo;
import com.stars.easyms.rest.bean.EasyMsRestContext;
import com.stars.easyms.rest.exception.AlarmException;
import com.stars.easyms.rest.exception.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;

/**
 * <p>className: EasyMsRestExceptionHandler</p>
 * <p>description: EasyMs的rest接口的异常信息处理类</p>
 *
 * @author guoguifang
 * @version 1.6.1
 * @date 2020/8/24 4:06 下午
 */
final class EasyMsRestExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(EasyMsRestExceptionHandler.class);

    static void handleRestAlarmException(Throwable throwable) {

        // 如果是未申报的异常类型则获取实际异常
        if (throwable instanceof UndeclaredThrowableException) {
            throwable = ((UndeclaredThrowableException) throwable).getUndeclaredThrowable();
        }
        boolean isBusinessException = throwable instanceof BusinessException;
        boolean isBusinessFeignException = throwable instanceof BusinessFeignException;

        // 获取rest执行方法并记录异常信息
        String fullMethodName = null;
        EasyMsRestContext easyMsRestContext = EasyMsRestSynchronizationManager.getEasyMsRestContext();
        String requestPath = easyMsRestContext.getEasyMsRequestEntity().getRequestPath();
        RestInfo restInfo = easyMsRestContext.getRestInfo();
        if (restInfo != null) {
            Method executeMethod = restInfo.getRestServiceMethod();
            if (executeMethod == null) {
                executeMethod = restInfo.getRestControllerMethod();
            }
            if (executeMethod != null) {
                fullMethodName = ReflectUtil.getMethodFullName(executeMethod);
            }
        }
        if (fullMethodName != null) {
            if (isBusinessException) {
                BusinessException businessException = (BusinessException) throwable;
                if (businessException.getCause() != null) {
                    logger.error("Method [{}] execute business failure! Request path: {}! Error message: {}",
                            fullMethodName, requestPath, businessException.getRetMsg(), businessException.getCause());
                } else {
                    // 如果是BusinessException并且不是由其他异常引发则使用info级别
                    logger.info("Method [{}] execute business failure! Request path: {}! Error message: {}",
                            fullMethodName, requestPath, businessException.getRetMsg());
                }
            } else if (isBusinessFeignException) {
                BusinessFeignException businessFeignException = (BusinessFeignException) throwable;
                // 如果是BusinessFeignException则使用info级别
                logger.info("Method [{}] execute feign failure! Error message: {}",
                        fullMethodName, businessFeignException.getRetMsg());
            } else {
                logger.error("Method [{}] execute failure! Request path: {}!", fullMethodName, requestPath, throwable);
            }
        } else {
            logger.error("Rest method execute failure! Request path: {}!", requestPath, throwable);
        }

        // 判断是否需要告警，告警异常为AlarmException或者非BusinessException及非BusinessFeignException
        boolean isAlarmException = throwable instanceof AlarmException;
        boolean isNeedAlarm = isAlarmException || (!isBusinessException && !isBusinessFeignException);
        if (isNeedAlarm) {
            EasyMsAlarmAssistor.sendExceptionAlarmMessage(throwable);
        }
    }

    private EasyMsRestExceptionHandler() {
    }

}